import os
import requests
from flask import Blueprint, send_from_directory, current_app, request, session, make_response
from shortuuid import uuid
from datetime import datetime
from exts import db
from models.user import UserModel
from hooks import login_auth
from utils import restful


bp = Blueprint("user", __name__, url_prefix="/user")


# 1、实现用户登录注册
@bp.route('/login', methods=['GET', 'POST'])
def user_login():
    data = request.json
    print(data)  # 字典类型的数据
    code = data['code']
    # 通过请求获取openid
    url = 'https://api.weixin.qq.com/sns/jscode2session'
    req_data = {'appid': 'wx20c4334aa81dff71',
                'secret': '207149e185d654e201700ff5d74e2e79',
                'js_code': code,
                'grant_type': 'authorization_code'}
    r = requests.get(url, req_data)
    # "https://api.weixin.qq.com/sns/jscode2session?appid=wx20c4334aa81dff71&secret=207149e185d654e201700ff5d74e2e79&js_code=0b1DsrFa1OjN4F0CwrHa1gKObW3DsrFC&grant_type=authorization_code"
    # print(r.url)
    # {"session_key": "EUPPH0vPN7Dbmzp8Kv46PQ==", "openid": "oLuIg4-kCmQ26L6DYeBYNx1JrrNE"}
    # print(r.json())
    # 进入注册登录程序
    rep_data = r.json()
    if 'errcode' in rep_data.keys():
        # return jsonify({'data': "", 'message': "请求失败"})
        return restful.server_error(message='请求失败')
    else:
        open_id = rep_data.get('openid')
        user = UserModel.query.get(open_id)
        if not user:
            # 未注册，进行注册
            user = UserModel(open_id=open_id)
            db.session.add(user)
            db.session.commit()
        # 设置session，记录登录状态
        session['open_id'] = open_id
        # 返回的数据信息
        user = get_user_info(open_id)
    # return jsonify(user)
    return restful.ok(message="登录成功", data=user)


# 2、上传头像图片，更新头像
@bp.route('/upload_avatar', methods=['POST'])
@login_auth
def img_upload():
    """
    接收小程序上传的头像文件，更新数据库信息，删除旧有头像
    :return: "" or "修改成功!"
    """
    # 获取上传文件和携带的参数，用于保存到本地和删除原有文件
    img = request.files.get("avatarImg")
    old_avatar = request.values.get('oldAvatar')  # 原来的avatar地址
    open_id = session.get('open_id')  # 用户的openId

    # 将图片名按照 . 进行切分， 找到文件的后缀名
    suffix = img.filename.rsplit('.')[-1]
    # 通过文件的后缀名判断身份为合法的图片
    if not img or suffix not in ['jpg', 'png', 'gif', 'jpeg']:
        # return ""
        return restful.params_error(message='文件格式错误')
    # 将图片对象存入本地，然后将路径存入数据库
    avatar_dir = os.path.join(current_app.config['IMAGE_ROOT'], 'avatar')  # 从app的配置项，取出IMAGE的路径
    filename = str(uuid()) + '.' + suffix  # 为了生成一个不重复的 文件名
    img_path = os.path.join(avatar_dir, filename)  # 将路径和文件名拼接在一起，方便保存文件

    # 输出日志信息
    current_app.logger.debug(f"图片存储路径为:{img_path}")
    # 将图片对象保存到本地
    img.save(img_path)

    # 将图片的url存入数据库，/user/getAvatar/文件名
    avatar_url = current_app.config['BASE_SERVER']+'/user/getAvatar/'+filename
    user = UserModel.query.get(open_id)
    user.avatar = avatar_url
    db.session.commit()

    # 删除本地原有的旧头像图片，节约内存
    old_filename = old_avatar.split('/')[-1]
    old_img_path = os.path.join(avatar_dir, old_filename)
    print('old_avatar', old_img_path)
    file_exist = os.path.exists(old_img_path)  # boolean
    if file_exist and old_filename not in ["default.jpg", "default.jpeg", "default.png", "default.gif", ""]:
        os.remove(old_img_path)
        # 输出警告日志信息
        current_app.logger.warning(f"{open_id}=>已删除头像文件:{old_img_path}")
        response = make_response("修改成功!", 200, {'avatar': avatar_url})
    # wx.upLoadFile()方法接收的返回参数只接收字符串，所以将avatar_url放到响应头中
    else:
        response = make_response("该文件不存在或已删除!!", 200, {'avatar': ""})
    return response


# 1-3、返回头像文件
@bp.route('/getAvatar/<string:file_name>', methods=['GET'])
def getLogFile(file_name):
    """
    根据用户请求返回头像图片
    :param file_name: 文件名,string
    :return: 文件对象 or 请求结果，str
    """
    try:
        image_dir = os.path.join(current_app.config['IMAGE_ROOT'], 'avatar')
        # 输出请求成功日志
        current_app.logger.info("请求成功")
        # 返回头像图片
        return send_from_directory(image_dir, file_name)
    except Exception as e:
        current_app.logger.error(e)
        return str(e)


# 2、修改用户信息
@bp.route('/update', methods=['PUT', 'POST'])
@login_auth
def update_user():
    open_id = session.get('open_id')
    # 1、获取上传json信息
    post_user = request.json
    print(post_user)
    # 2、将生日字符串转化为Date对象
    user = UserModel.query.get(open_id)
    username = post_user.get('username')
    birthday = post_user.get('birthday')
    self_intro = post_user.get('self_intro')
    if username and 2 <= len(username) <= 20:
        user.username = post_user['username']
    if birthday and birthday != '':
        user.birthday = datetime.strptime(birthday, '%Y-%m-%d').date()
        print(user.birthday)
    user.self_intro = self_intro
    # 3、写入数据库
    db.session.commit()
    # 4、返回信息
    return restful.ok(message="修改成功")


# 3、刷新获取用户最新信息
@bp.route('/refresh', methods=['GET'])
@login_auth
def get_info_refresh():
    open_id = session.get('open_id')
    user = get_user_info(open_id)
    return restful.ok(message="请求成功", data=user)


# 4、用户最高管理权限验证
@bp.route('/adminCheck', methods=['GET'])
@login_auth
def admin_check():
    open_id = session.get('open_id')
    user = UserModel.query.get(open_id)
    if user and user.role == 1:
        return restful.ok(message='验证通过')
    return restful.permission_error()


# 获取用户信息，包括基础信息+收藏和博客信息
def get_user_info(open_id):
    user = UserModel.query.get(open_id)
    res = user.to_dict()
    # 涉及到博客和收藏操作
    res['blog_num'] = len(user.blogs.all())
    res['star_num'] = len(user.starlists.all())
    return res


# 5、管理员获取用户信息
@bp.route('/adminGet/<int:page>/<string:name>', methods=['GET'])
@login_auth
def get_user_admin(page, name):
    us = []
    page_size = current_app.config['USER_PER_PAGE']
    offset = (page-1) * page_size
    if name != "all":
        query = UserModel.query.filter(UserModel.username.contains(name)).offset(offset)
    else:
        query = UserModel.query.offset(offset)
    users = query.limit(page_size).all()
    for u in users:
        us.append(u.to_dict(choice='admin'))
    return restful.ok(data={'users': us})


@bp.route('/adminUpdate/<string:uid>/<string:permission>', methods=["POST", "PUT"])
def update_user_admin(uid,permission):
    user = UserModel.query.get(uid)
    if permission == 'allow_comment' and user:
        user.allow_comment = not user.allow_comment
    elif permission == 'allow_blog' and user:
        user.allow_blog = not user.allow_blog
    else:
        return restful.params_error()
    return restful.ok()
